#coding=utf-8
#auth:beck shen
#date:2017-10-18

from pytw.tools import log

import stackless

from twisted.internet import defer, reactor


class _TaskletProperty(object):

    """
    方便获取stackless.tasklet._tasklet
    """

    def __get__(self, obj, cls):
        return stackless.getcurrent()._tasklet

    def __set__(self, obj, value):
        pass

    def __delete(self, obj):
        pass


class Tasklet(object):

    """
    重写封装stackless.tasklet对象，结合twisted中的
    defer,不再需要addCallback；并且所有在tasklet对象
    中运行的函数的参数通过current_tasklet.args, 
    current_tasklet.kwargs获取
    """
    
    current = _TaskletProperty()

    def __init__(self, handler, args, kwargs):
        self.handler = handler
        self.args = args
        self.kwargs = kwargs

        self._channel = stackless.channel()

    @classmethod
    def create(cls, handler, *args, **kwargs):
        """
        创建Tasklet对象
        """
        obj = cls(handler, args, kwargs)
        t = stackless.tasklet(handler)()
        t._tasklet = obj
        return obj

    def sleep(t):
        """
        异步等待多少秒
        """
        if time < 0:
            return
        d = defer.Deferred()
        reactor.callLater(t, d.callback, None)
        self.get_result(d)       
 
    def get_result(self, d):
        """
        获取defer返回结果
        """
        d.addCallback(self._on_success)
        d.addErrback(self._on_error)
        #channel等待结果
        result = self._channel.receive() 
        return result

    def _on_success(self, result):
        """
        defer成功，通过channel发送结果
        """
        self._channel.send(result)

    def _on_error(self, error):
        """
        defer失败回调，抛出异常
        """
        log.err("run_in_tasklet_error===>:", 
                    self.handler, 
                    self.args,
                    self.kwargs,
                    error)
        self._channel.send_exception(error.type, error.value)
    
